package com.cn.web.dao.utils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;

import org.apache.commons.lang3.StringUtils;

import com.cn.web.entity.BaseEntity;
import com.cn.web.exception.ParameterException;
import com.cn.web.exception.SqlProviderException;


/**
 * 反射解析Entity类
 * 
 * @author love
 */
public class EntityUtil {

	//用于存放Entity的列信息
	private static Map<Class<?>, List<Field>> columnMap = new HashMap<Class<?>, List<Field>>();

	/**
	 * 获取Entity对应的表名 需要Entity中的属性定义注解@Table(name)
	 * 
	 * @return 注解表名
	 * @throws Exception
	 */
	public static String tablename(Object obj) throws Exception {
		Table table = obj.getClass().getAnnotation(Table.class);
		if (table != null)
			return table.name();
		else
			throw new SqlProviderException("需要在" + obj.getClass() + "中添加注解@Table(name)！");
	}

	/**
	 * 获取Entity中注解@Column的列(数据库中字段名)
	 * 
	 * @param entity entity实体对象
	 */
	public static void caculationColumnList(Object entity) {
		if (columnMap.containsKey(entity.getClass()))
			return;
		List<Field> columnList = new ArrayList<Field>();

		Field[] fields = entity.getClass().getDeclaredFields();

		for (Field f : fields) {
			// 1、获取属性上的指定类型的注释
			Annotation annotation = f.getAnnotation(Column.class);

			// 有该类型的注释存在
			if (annotation != null) {
				columnList.add(f);
			}
		}
		columnMap.put(entity.getClass(), columnList);
	}

	/**
	 * 
	 * 用于获取Insert的字段累加
	 * 
	 * @param entity entity实体对象
	 * @return 
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public static String returnInsertColumnsName(Object entity)  throws IllegalArgumentException, IllegalAccessException {
		StringBuilder sb = new StringBuilder("");
		String idName = getTableKey(entity);
		List<Field> propertyList = columnMap.get(entity.getClass());
		for (Field field : propertyList) {
			String table_column="";
			Annotation annotation = field.getAnnotation(Column.class);
			if (annotation != null) {
				Column tblElement = (Column) annotation;
				if (StringUtils.isNotEmpty(tblElement.name())) {
					table_column = tblElement.name();
				} else {
					table_column = CamelNameUtils.camelhumpToUnderline(field.getName()).toLowerCase();
				}				
			}else{
				continue;
			}
			
			field.setAccessible(true);
			if (idName.equals(field.getName()) || null == field.get(entity)) {
				continue;
			}
			if (StringUtils.isNotBlank(sb.toString())) {
				sb.append(',');
			}
			sb.append(table_column);
		}
		System.out.println(sb.toString());
		return sb.toString();
	}

	/**
	 * 
	 * 用于获取Insert的字段映射累加
	 * 
	 * @param entity entity实体对象
	 * @return 
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */	
	public static String returnInsertColumnsDefine(Object entity) throws IllegalArgumentException, IllegalAccessException {
		StringBuilder sb = new StringBuilder();

		String idName = getTableKey(entity);
		List<Field> propertyList = columnMap.get(entity.getClass());
		for (Field field : propertyList) {
			String column="";
			Annotation annotation = field.getAnnotation(Column.class);
			if (annotation != null) {
				column = field.getName();				
			}else{
				continue;
			}
			
			field.setAccessible(true);
			if (idName.equals(field.getName()) || null == field.get(entity)) {
				continue;
			}
			if (StringUtils.isNotBlank(sb.toString())) {
				sb.append(',');
			}
			sb.append("#{").append(column).append('}');
		}
		System.out.println(sb.toString());		
		
		return sb.toString();
	}

	/**
	 * 
	 *  获取Entity中的主键字段名 需要定义@Id
	 * 
	 * @param entity entity实体对象
	 * @return 
	 */		
	public static String getTableKey(Object entity) {
		String idName = "";
		Field[] fields = entity.getClass().getDeclaredFields();

		for (Field f : fields) {
			String filedName = f.getName();

			// 1、获取属性上的指定类型的注释
			Annotation annotation = f.getAnnotation(Id.class);

			// 有该类型的注释存在
			if (annotation != null) {
				idName = filedName;
				break;
			}
		}
		if(StringUtils.isEmpty(idName)){
			throw new ParameterException(entity.getClass() + "中没有定义主键！");
		}
		return idName;
	}

	
	/**
	 * 
	 *  获取Entity中的主键字段名 需要定义@Id
	 * 
	 * @param entity entity实体对象
	 * @return 
	 */			
	public static String getUpdateWhere(Object entity) {
		String idname = getTableKey(entity);
		String sqlWhere = idname + "=#{" + idname + "} and record_status = 1 ";
		return sqlWhere;
	}
	
	
	/**
	 * 更新时更新字段拼接
	 * 
	 * @param entity entity实体对象
	 * @return 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	public static String getUpdateSet(Object entity) throws IllegalArgumentException, IllegalAccessException {
		StringBuilder sb = new StringBuilder("");
		
		String idName = getTableKey(entity);
		List<Field> propertyList = columnMap.get(entity.getClass());
		for (Field field : propertyList) {
			String table_column="";
			Annotation annotation = field.getAnnotation(Column.class);
			if (annotation != null) {
				Column tblElement = (Column) annotation;
				if (StringUtils.isNotEmpty(tblElement.name())) {
					table_column = tblElement.name();
				} else {
					table_column = CamelNameUtils.camelhumpToUnderline(field.getName()).toLowerCase();
				}				
			}else{
				continue;
			}
			
			field.setAccessible(true);
			if (idName.equals(field.getName()) || null == field.get(entity)) {
				continue;
			}
			
			// 不为基本数据类型,不进入更新
			Class<?> type = field.getType();
			if (!(type == Byte.class
					|| type == Character.class
					|| type == Boolean.class
					|| type == Integer.class
					|| type == Long.class
					|| type == Float.class
					|| type == Double.class
					|| type == String.class
					|| type == Date.class)) {
				continue;
			}
			
			if (StringUtils.isNotBlank(sb.toString())) {
				sb.append(',');
			}
			sb.append(table_column);
			sb.append("=#{").append(field.getName()).append('}');
			
		}
		return sb.toString();
	}
	
	
	
	/**
	 * 逻辑删除时拼接字段
	 * 
	 * @return
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	public static String getDeleteSet(Object entity) throws IllegalArgumentException, IllegalAccessException {
		StringBuilder sb = new StringBuilder("");
		
		String idName = getTableKey(entity);
		List<Field> propertyList = columnMap.get(entity.getClass());
		for (Field field : propertyList) {
			String table_column="";
			if(!("recordStatus".equals(field.getName()) 
					|| "updateUser".equals(field.getName())
					|| "updateTime".equals(field.getName()))){
				continue;
			}
			
			Annotation annotation = field.getAnnotation(Column.class);
			if (annotation != null) {
				Column tblElement = (Column) annotation;
				if (StringUtils.isNotEmpty(tblElement.name())) {
					table_column = tblElement.name();
				} else {
					table_column = CamelNameUtils.camelhumpToUnderline(field.getName()).toLowerCase();
				}				
			}else{
				continue;
			}
			
			field.setAccessible(true);
			if (idName.equals(field.getName()) || null == field.get(entity)) {
				continue;
			}
			
			// 不为基本数据类型,不进入更新
			Class<?> type = field.getType();
			if (!(type == Byte.class
					|| type == Character.class
					|| type == Boolean.class
					|| type == Integer.class
					|| type == Long.class
					|| type == Float.class
					|| type == Double.class
					|| type == String.class
					|| type == Date.class)) {
				continue;
			}
			
			if (StringUtils.isNotBlank(sb.toString())) {
				sb.append(',');
			}
			sb.append(table_column);
			sb.append("=#{").append(field.getName()).append('}');
			
		}
		return sb.toString();
	}
	
	
	/**
	 * 用于获取Select的字段映射(关键字检索 + 条件检索)
	 * @param entityClass entity对象类型
	 * @return
	 */
	public static String getSelectColumnsName(Class<?> entityClass) {
		StringBuilder sb = new StringBuilder("");

		Field[] fields = entityClass.getDeclaredFields();

		for (Field f : fields) {
			// 1、获取属性上的指定类型的注释
			Annotation annotation = f.getAnnotation(Column.class);
			
			String table_column="";
			// 有该类型的注释存在
			if (annotation != null) {
				Column tblElement = (Column) annotation;
				if (StringUtils.isNotEmpty(tblElement.name())) {
					
					table_column = tblElement.name();
				} else {
					table_column = CamelNameUtils.camelhumpToUnderline(f.getName()).toLowerCase();
				}
				if (StringUtils.isNotBlank(sb.toString())) {
					sb.append(',');
				}
				sb.append(table_column);
				sb.append(" as ");
				sb.append(f.getName());
			}
		}
		return sb.toString();
	}
	
	
	/**
	 * 获取entityClass对应的表名
	 * 
	 * 需要entityClass中的属性定义@Table(name)
	 * @return
	 * @throws Exception 
	 */
	public static String getSelectTableName(Class<?> entityClass) throws Exception {
		Table table = (Table) entityClass.getAnnotation(Table.class);
		if(table != null)
			return table.name();
		else
			throw new SqlProviderException("需要在" + entityClass+ "中添加注解@Table(name)！");
	}
	
	/**
	 * 检索时的where条件拼成 (关键字检索 )
	 * 
	 * @return
	 */
	public static String getSelectByKey() {
		String sqlWhere =   " id =#{id} and record_status = 1 ";
		return sqlWhere;
	}
	
	/**
	 * 用于获取Select的字段映射(关键字检索 + 条件检索)
	 * @param entityClass entity对象类型
	 * @return
	 */
	public static String getSelectSql(Object entity) {
		BaseEntity baseEntity  = (com.cn.web.entity.BaseEntity) entity;
		return baseEntity.getQuery().getSql();
	}
}
